package com.guodi.model.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.guodi.common.constant.StatusCode;
import com.guodi.common.utils.AjaxResult;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.core.tool.utils.Func;
import com.guodi.model.entity.IdtIndicatorsDir;
import com.guodi.model.entity.IdtIndicatorsType;
import com.guodi.model.entity.IdtModelLayer;
import com.guodi.model.service.IIdModelLayerService;
import com.guodi.model.service.IIdtIndicatorsDirService;
import com.guodi.model.service.IIdtIndicatorsTypeService;
import com.guodi.model.utils.RecursionUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import javax.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @描述：指标分类表控制类
 * @作者: 彭辉
 * @日期: 2020-06-05
 */
@RestController
@RequestMapping("/IdtIndicatorsType")
@Api(value = "API - IdtIndicatorsTypeController", description = "指标分类表")
public class IdtIndicatorsTypeController extends BaseController {

    @Resource
    public IIdtIndicatorsTypeService idtIndicatorsTypeService;

    @Resource
    public IIdtIndicatorsDirService iIdtIndicatorsDirService;
    @Resource
    public IIdModelLayerService iIdModelLayerService;


    /**
     * @描述: 根据体系编码、年份、行政区划，寻找对应的指标体系解决方案
     * @作者: 陈宏成
     * @日期: 2021-11-30
     **/
    @PostMapping("/findByCode")
    @ApiOperation(value = "根据体系编码、年份、行政区划，寻找对应的指标体系解决方案")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "体系编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "divisionCode", value = "行政区划代码", required = true, dataType = "string", paramType = "query"),
    })
    public AjaxResult findByCode(String code, String year, String divisionCode){
        IdtIndicatorsType byCode = this.idtIndicatorsTypeService.findByCode(code, year, divisionCode);
        return new AjaxResult(byCode);
    }

    /**
     * @描述: 新增
     * @入参:
     * @出参:
     * @作者: 彭辉
     * @日期: 2020-06-05
     **/
    @PostMapping("/save")
    @ApiOperation(value = "新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "名称", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "parentId", value = "上级目录", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "divisionCode", value = "行政区划代码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "year", value = "年份", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult save(@ApiIgnore IdtIndicatorsType idtIndicatorsType){
        String deptId = this.getUser().getDeptId();
        if (StringUtils.isBlank(deptId)) {
            return new AjaxResult(StatusCode.ERROR_CODE_40005, "该用户所属机构不存在");
        }
        if(StringUtils.isNotBlank(idtIndicatorsType.getParentId()) && idtIndicatorsType.getParentId().equals("-1")){
            // 只有根目录才验证code, 去除数据库code必填
            HashMap map = new HashMap();
            map.put("code",idtIndicatorsType.getCode());
            Collection collection = idtIndicatorsTypeService.listByMap(map);
            if (collection.size() > 0) {
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "该编码已存在，请更换！");
            }
            // 检查名字是否唯一
            boolean checkNameExistForType = this.idtIndicatorsTypeService.checkNameExistForType(idtIndicatorsType.getName(), idtIndicatorsType.getId());
            if(checkNameExistForType == true){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "该名称已存在，请更换！");
            }
        }else {
            // 验证名称是否重复
            IdtIndicatorsType idtType = this.idtIndicatorsTypeService.getById(idtIndicatorsType.getParentId());
            if (Objects.isNull(idtType)) {
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "目标指标体系不存在");
            }
            boolean checkNameExist = this.idtIndicatorsTypeService.checkNameExistInType(idtType.getCode(), idtIndicatorsType.getName(), idtIndicatorsType.getId());
            if(checkNameExist == true){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "该名称已存在，请更换！");
            }
            // 非根目录则验证年份、行政区划是否存在重复
            List<String> currentYears = new ArrayList<>(Func.toStrList(idtIndicatorsType.getYear()));
            List<String> currentDivisionCodes = new ArrayList<>(Func.toStrList(idtIndicatorsType.getDivisionCode()));
            HashMap map = new HashMap();
            map.put("parent_id",idtIndicatorsType.getParentId());
            List<IdtIndicatorsType> idtIndicatorsTypes = idtIndicatorsTypeService.listByMap(map);
            if(idtIndicatorsTypes.size() > 0){
                // 1.先验证年份是否有重复
                for (IdtIndicatorsType indicatorsType: idtIndicatorsTypes) {
                    List<String> oldYears = new ArrayList<>(Func.toStrList(indicatorsType.getYear()));
                    List<String> oldDivisionCodes = new ArrayList<>(Func.toStrList(indicatorsType.getDivisionCode()));
                    int oldDivisionCodeSize = oldDivisionCodes.size();
                    int oldYearSize = oldYears.size();
                    oldDivisionCodes.addAll(currentDivisionCodes);
                    oldYears.addAll(currentYears);
                    // 判断年份是否一致
                    if(indicatorsType.getYear().equals(idtIndicatorsType.getYear())){
                        // 年份一致则判断行政区划是否包含重复数据
                        int newDivisionSize = oldDivisionCodes.stream().distinct().collect(Collectors.toList()).size();
                        if(newDivisionSize != (oldDivisionCodeSize + currentDivisionCodes.size())){
                            return new AjaxResult(StatusCode.ERROR_CODE_40005,"同年份/行政区划指标体系已存在!");
                        }
                    }else{
                        // 1.取出重复的年份
                        int newYearsSize = oldYears.stream().distinct().collect(Collectors.toList()).size();
                        if(newYearsSize != (oldYearSize + currentYears.size())){
                            // 说明存在包含关系，则对比行政区划
                            int newDivisionSize = oldDivisionCodes.stream().distinct().collect(Collectors.toList()).size();
                            if(newDivisionSize != (oldDivisionCodeSize + currentDivisionCodes.size())){
                                return new AjaxResult(StatusCode.ERROR_CODE_40005,"同年份/行政区划指标体系已存在!");
                            }
                        }
                        /*// 年份不一致则比较年份是否包含重复
                        if(!(Integer.parseInt(currentYears.get(currentYears.size() - 1)) < Integer.parseInt(oldYears.get(0)) ||
                                Integer.parseInt(currentYears.get(0)) > Integer.parseInt(oldYears.get(oldYears.size() - 1)))){
                            return new AjaxResult(StatusCode.ERROR_CODE_40005,"同年份/行政区划指标体系已存在!");
                        }*/
                    }
                }
            }
        }
        prepareData(idtIndicatorsType, true);
        if (idtIndicatorsType.getStatus() == null) {
            idtIndicatorsType.setStatus(1);
        }
        if(idtIndicatorsType.getSort() == null){
            idtIndicatorsType.setSort(idtIndicatorsTypeService.selectMaxSort()+1);
        }
        idtIndicatorsType.setId(UuidUtil.get32UUID());
        idtIndicatorsType.setOrgId(deptId);
        //保存
        boolean bol = idtIndicatorsTypeService.save(idtIndicatorsType);
        if(bol){
            return new AjaxResult(idtIndicatorsType);
        }else {
            return new AjaxResult(StatusCode.REQUEST_CODE_OPERATION_FAILURE, "保存失败");
        }
    }

    /**
     * @描述: 修改
     * @入参:
     * @出参:
     * @作者: 彭辉
     * @日期: 2020-06-05
     **/
    @PostMapping("/update")
    @ApiOperation(value = "修改")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult update(IdtIndicatorsType idtIndicatorsType) {
        String deptId = this.getUser().getDeptId();
        if (StringUtils.isBlank(deptId)) {
            return new AjaxResult(StatusCode.ERROR_CODE_40005, "改用户所属部门不存在");
        }
        prepareData(idtIndicatorsType, false);
        if (StringUtils.isNotBlank(idtIndicatorsType.getCode()) && idtIndicatorsType.getParentId().equals("-1")) {
            HashMap hashMap = new HashMap();
            hashMap.put("code",idtIndicatorsType.getCode());
            //验证修改的code唯一
            List<IdtIndicatorsType> list = (List<IdtIndicatorsType>) idtIndicatorsTypeService.listByMap(hashMap);
            if (list.size() > 0 && !list.get(0).getId().equals(idtIndicatorsType.getId())) {
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "该编码已经存在,请更换！");
            }
            // 检查名字是否唯一
            boolean checkNameExistForType = this.idtIndicatorsTypeService.checkNameExistForType(idtIndicatorsType.getName(), idtIndicatorsType.getId());
            if(checkNameExistForType == true){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "该名称已存在，请更换！");
            }
        }else {
            // 验证名称是否重复
            IdtIndicatorsType idtType = this.idtIndicatorsTypeService.getById(idtIndicatorsType.getParentId());
            if (Objects.isNull(idtType)) {
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "目标指标体系不存在");
            }
            boolean checkNameExist = this.idtIndicatorsTypeService.checkNameExistInType(idtType.getCode(), idtIndicatorsType.getName(), idtIndicatorsType.getId());
            if(checkNameExist == true){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "该名称已存在，请更换！");
            }
            // 非根目录则验证年份、行政区划是否存在重复
            List<String> currentYears = new ArrayList<>(Func.toStrList(idtIndicatorsType.getYear()));
            List<String> currentDivisionCodes = new ArrayList<>(Func.toStrList(idtIndicatorsType.getDivisionCode()));
            LambdaQueryWrapper<IdtIndicatorsType> queryWrapper = (new QueryWrapper()).lambda();
            queryWrapper.eq(IdtIndicatorsType::getParentId, idtIndicatorsType.getParentId());
            queryWrapper.ne(IdtIndicatorsType::getId, idtIndicatorsType.getId());
            List<IdtIndicatorsType> idtIndicatorsTypes = idtIndicatorsTypeService.list(queryWrapper);
            if(idtIndicatorsTypes.size() > 0){
                // 1.先验证年份是否有重复
                for (IdtIndicatorsType indicatorsType: idtIndicatorsTypes) {
                    List<String> oldYears = new ArrayList<>(Func.toStrList(indicatorsType.getYear()));
                    List<String> oldDivisionCodes = new ArrayList<>(Func.toStrList(indicatorsType.getDivisionCode()));
                    int oldDivisionCodeSize = oldDivisionCodes.size();
                    int oldYearSize = oldYears.size();
                    oldDivisionCodes.addAll(currentDivisionCodes);
                    oldYears.addAll(currentYears);
                    // 判断年份是否一致
                    if(indicatorsType.getYear().equals(idtIndicatorsType.getYear())){
                        // 年份一致则判断行政区划是否包含重复数据
                        int newDivisionSize = oldDivisionCodes.stream().distinct().collect(Collectors.toList()).size();
                        if(newDivisionSize != (oldDivisionCodeSize + currentDivisionCodes.size())){
                            return new AjaxResult(StatusCode.ERROR_CODE_40005,"同年份/行政区划指标体系已存在!");
                        }
                    }else{ // 年份不一致则比较年份是否包含重复
                        // 1.取出重复的年份
                        int newYearsSize = oldYears.stream().distinct().collect(Collectors.toList()).size();
                        if(newYearsSize != (oldYearSize + currentYears.size())){
                            // 说明存在包含关系，则对比行政区划
                            int newDivisionSize = oldDivisionCodes.stream().distinct().collect(Collectors.toList()).size();
                            if(newDivisionSize != (oldDivisionCodeSize + currentDivisionCodes.size())){
                                return new AjaxResult(StatusCode.ERROR_CODE_40005,"同年份/行政区划指标体系已存在!");
                            }
                        }
                        /*if(!(Integer.parseInt(currentYears.get(currentYears.size() - 1)) < Integer.parseInt(oldYears.get(0)) ||
                                Integer.parseInt(currentYears.get(0)) > Integer.parseInt(oldYears.get(oldYears.size() - 1)))){
                            return new AjaxResult(StatusCode.ERROR_CODE_40005,"同年份/行政区划指标体系已存在!");
                        }*/
                    }
                }
            }
        }
        idtIndicatorsType.setOrgId(deptId);
        Boolean bol =idtIndicatorsTypeService.updateById(idtIndicatorsType);
        if(bol){
            return new AjaxResult(idtIndicatorsType);
        }else {
            return new AjaxResult(StatusCode.REQUEST_CODE_OPERATION_FAILURE, "修改失败");
        }
    }

    /**
     * @描述: 根据主键删除
     * @入参: id
     * @出参:
     * @作者: 彭辉
     * @日期: 2020-06-05
     **/
    @PostMapping("/delete")
    @ApiOperation(value = "根据主键删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", required = true,
                    dataType = "string", paramType = "query")
    })
    public AjaxResult delete(String id){
        //递归删除子表的数据
        iIdtIndicatorsDirService.deleteByParentId(id);
        //删除主列表数据
        idtIndicatorsTypeService.deleteByParentId(id);
        return new AjaxResult();
    }

    /**
    * @描述: 返回表中所有的记录
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2021/9/27 15:38
    **/
    @PostMapping("/listByKeyWord")
    @ApiOperation(value = "返回表中所有的记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "keyWord", value = "关键字,不传默认列出所有的数据", dataType = "string", paramType = "query")
    })
    public AjaxResult listByKeyWord(String keyWord) {
        List<IdtIndicatorsType> idtIndicatorsTypeList;
        LambdaQueryWrapper<IdtIndicatorsType> queryWrapper = (new QueryWrapper()).lambda();
        //根据字段升序排序
        queryWrapper.orderByAsc(IdtIndicatorsType::getSort);
        if (StringUtils.isNotBlank(keyWord)) {
            queryWrapper.like(IdtIndicatorsType::getName, keyWord).or().like(IdtIndicatorsType::getCode, keyWord);
        }
        idtIndicatorsTypeList = idtIndicatorsTypeService.list(queryWrapper);
        return new AjaxResult(RecursionUtils.buildIdtIndicatorsTypeTree(idtIndicatorsTypeList));
    }

    /**
    * @描述: 根据指标体系编码返回子节点指标系统列表
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2021/10/8 11:35
    **/
    @PostMapping("/listByType")
    @ApiOperation(value = "根据指标体系编码返回子节点指标系统列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "idtType", value = "指标编码", dataType = "string", required = true, paramType = "query")
    })
    public AjaxResult listByType(String idtType) {
        List<IdtIndicatorsType> idtIndicatorsTypeList = idtIndicatorsTypeService.listByType(idtType);
        return new AjaxResult(idtIndicatorsTypeList);
    }

    /**
    * @描述: 复制指标体系目录树
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2021/10/21 15:20
    **/
    @PostMapping("/copyDataById")
    @ApiOperation(value = "复制指标体系目录树")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "targetId", value = "待复制指标体系ID", dataType = "string", required = true, paramType = "query"),
            @ApiImplicitParam(name = "id", value = "新生成指标体系ID", dataType = "string", required = true, paramType = "query")
    })
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult copyDataById(String targetId, String id){
        // 查询待复制的指标目录树列表
        List<IdtIndicatorsDir> targetList = iIdtIndicatorsDirService.getAllByParentId(targetId, null);
        // 重新组装复制数据
        List<IdtModelLayer> layers = new ArrayList<>();
        List<IdtIndicatorsDir> idtIndicatorsDirs = rebuildList(targetList, targetId, id,layers);
        iIdtIndicatorsDirService.saveBatch(idtIndicatorsDirs);
        if(!CollectionUtils.isEmpty(layers)){
            iIdModelLayerService.saveBatch(layers);
        }
        return new AjaxResult(idtIndicatorsDirs);
    }

    public List<IdtIndicatorsDir> rebuildList(List<IdtIndicatorsDir> idtIndicatorsDirs, String oldParentId, String newParentId,List<IdtModelLayer> layers){
        List<IdtIndicatorsDir> idtIndicatorsDirList = new ArrayList<>();
        for (IdtIndicatorsDir idtIndicatorsDir:idtIndicatorsDirs) {
            String oldId = idtIndicatorsDir.getId();
            idtIndicatorsDir.setId(UuidUtil.get32UUID());
            for(IdtIndicatorsDir indicatorsDir: idtIndicatorsDirs){
                if(indicatorsDir.getParentId().equals(oldId)){
                    indicatorsDir.setParentId(idtIndicatorsDir.getId());
                }
                if(indicatorsDir.getParentId().equals(oldParentId)){
                    indicatorsDir.setParentId(newParentId);
                }
            }
            // 新增的数据
            idtIndicatorsDir.setCreateTime(new Date());
            idtIndicatorsDir.setCreator(getUser().getUserId().toString());
            idtIndicatorsDir.setModifier(null);
            idtIndicatorsDir.setModifyTime(null);
            idtIndicatorsDirList.add(idtIndicatorsDir);

            //新增关联的图层
            LambdaQueryWrapper<IdtModelLayer> wrapper =new LambdaQueryWrapper<>();
            wrapper.eq(IdtModelLayer::getParentId,oldId);
            List<IdtModelLayer> layerList = iIdModelLayerService.list(wrapper);
            if(!CollectionUtils.isEmpty(layerList)){
                for(IdtModelLayer idtModelLayer : layerList){
                    idtModelLayer.setParentId(idtIndicatorsDir.getId());
                    idtModelLayer.setId(UuidUtil.get32UUID());
                    idtModelLayer.setCreateTime(new Date());
                    idtModelLayer.setSystemId(newParentId);
                    idtModelLayer.setCreator(getUser().getUserId().toString());
                    idtModelLayer.setModifier(null);
                    idtModelLayer.setModifyTime(null);
                    layers.add(idtModelLayer);
                }
            }
        }
        return idtIndicatorsDirList;
    }

    private void prepareData(IdtIndicatorsType idtIndicatorsType, boolean isSave) {
        if(isSave){
            idtIndicatorsType.setCreator(this.getUser().getUserId().toString());
            idtIndicatorsType.setCreateTime(new Date());
            //防止误修改
            idtIndicatorsType.setModifier(null);
            idtIndicatorsType.setModifyTime(null);
        }else{
            idtIndicatorsType.setModifier(this.getUser().getUserId().toString());
            idtIndicatorsType.setModifyTime(new Date());
            //防止误修改
            idtIndicatorsType.setCreator(null);
            idtIndicatorsType.setCreateTime(null);
        }
    }
}
